#ifndef DW_MATHS_SHAPE_H
#	define DW_MATHS_SHAPE_H

#include "maths/intersection.h"

namespace dw {
	namespace maths {

struct Ray;
struct Sphere;
struct AABBox;

struct Shape
{
public : //! @name Types definitions
	//! @{
	enum Type
	{
		Type_Invalid = -1,
		Type_Ray,
		Type_Sphere,
		Type_AABBox
	};
	//! @}

public : //! @name Construction & Destruction
	//! @{
	Shape(Type pType) : type(pType) { ; }
	//! @}

public : //! @name Commands
	//! @{
	static bool intersects(const Shape& shapeA, const Shape& shapeB);
	static bool intersects(const Shape& shapeA, const Shape& shapeB, Intersection& intersection);

	// Ray
	static bool intersects(const Ray& shapeA, const Ray& shapeB);
	static bool intersects(const Ray& shapeA, const Ray& shapeB, Intersection& intersection);

	static bool intersects(const Ray& shapeA, const Sphere& shapeB);
	static bool intersects(const Ray& shapeA, const Sphere& shapeB, Intersection& intersection);

	static bool intersects(const Ray& shapeA, const AABBox& shapeB);
	static bool intersects(const Ray& shapeA, const AABBox& shapeB, Intersection& intersection);

	// Sphere
	static bool intersects(const Sphere& shapeA, const Ray& shapeB);
	static bool intersects(const Sphere& shapeA, const Ray& shapeB, Intersection& intersection);

	static bool intersects(const Sphere& shapeA, const Sphere& shapeB);
	static bool intersects(const Sphere& shapeA, const Sphere& shapeB, Intersection& intersection);

	static bool intersects(const Sphere& shapeA, const AABBox& shapeB);
	static bool intersects(const Sphere& shapeA, const AABBox& shapeB, Intersection& intersection);

	// AABBox
	static bool intersects(const AABBox& shapeA, const Ray& shapeB);
	static bool intersects(const AABBox& shapeA, const Ray& shapeB, Intersection& intersection);

	static bool intersects(const AABBox& shapeA, const Sphere& shapeB);
	static bool intersects(const AABBox& shapeA, const Sphere& shapeB, Intersection& intersection);

	static bool intersects(const AABBox& shapeA, const AABBox& shapeB);
	static bool intersects(const AABBox& shapeA, const AABBox& shapeB, Intersection& intersection);
	//! @}

public : //! @name Helpers
	//! @{
	static void swapIntersectionResult(Intersection& intersection);

	//! \brief Find the closest point from p in shape
	static Vector3f getClosestPoint(const Vector3f& p, const Ray& shape);
	static Vector3f getClosestPoint(const Vector3f& p, const Sphere& shape);
	static Vector3f getClosestPoint(const Vector3f& p, const AABBox& shape);
	//! @}

public : //! @name Data
	//! @{
	Type type;
	//! @}
};

	} // namespace maths
} // namespace dw

#endif // !DW_MATHS_SHAPE_H
